本篇將介紹何謂 object pool 模式,提及的案例是本書作者實際遇到的專案問題。
這一章 (Chapter 22) 有一些篇幅放在除了實踐此模式外的錯誤處理,在這裡先暫時不 cover 那一部分,有興趣可以去看看。
我將直接把這章的案例整理出來,並看看作者碰到什麼樣的難題。
這項專案是開發一個 Web 的個人投資系統。這個系統是讓使用者透過網頁查看自己的個人投資狀況,下訂單、做各種買賣。在這個案例中,各種使用者資訊是儲存在一個大型機上,與其連接的方式是透過固定的通訊協定並透過 TCP/IP 連接。
現在需要做的是:設計一個與大型機連接的一個處理器系統。同時,作者提到此專案的要求是關注輸送量,而不要太在乎回應時間。這個請求代表著需要處理盡可能多的事物,而無須擔心某個執行緒透過系統的時間。
作者列出需要處理的問題
首先,我們可以先將上述問題封裝起來,讓它與商務邏輯隔離開來:主要商業邏輯實際上只會碰觸到一個 TCP/IP 連接。連接如何工作、有多少個連接,以及如何處理錯誤,都是那些「連接到連接」的程式碼要處理的問題。
同時我們也希望設計出來的解決方案能在不影響商務邏輯相關的程式碼下修改 TCP/IP 的數量。換句話說,客戶物件無需知道這方面的資訊。
我們需要設計與大型機通訊的 TCP/IP 物件與一個管理 TCP/IP 物件的物件。我們用聚合的方式,設計一個 Port
物件使用 TCP/IP 物件,並且實作與其相關的各種邏輯操作。
我們可能會有很多個 Port
,而這些 Port
會由一個且僅有一個 PortManager
集中管理。在這裡會運用到 singleton 模式來確保我們只會有一個 PortManager
。
PortManager
的實作如下:
Port
參照的陣列,並且在建構函數中實體化它們getInstanceOfPort()
:呼叫而得到一個 Port
(用迴圈尋找狀態為未使用的 Port
,取出並更新狀態為使用中;如果找不到,sleep 1s 再執行一次)returnInstanceOfPort(Port portToRelease)
:告知指定的 Port
不再活動(找到指定的參照,並更新狀態為未使用)而客戶物件要做的事情就只有
PortManager
請求一個 Port
Port
Port
而這就是 Object Pool 模式。
註:此模式並不是來自於《DESIGN PATTERN》,而是在 Mark Grand 的《Patterns in Java》中提及。另一位作者 Clifton Nock 的《Data Access Pattern》在資料庫資源背景下也詳細地討論了這個模式,在該書被稱為 Resource Pool 模式。
因此,這一篇 GoF 先沒有出來開示(?)。
以下是此模式的關鍵特徵。
項目 | 內容 |
---|---|
意圖 | 在建立物件比較昂貴,或者對於特定類型能夠建立的物件數有限制時,管理物件的再利用。 |
問題 | 物件的建立和/或管理必須遵循一組定義明確的規則集。通常這些規則都與如何建立物件、能夠建立多少物件和在已有物件完成目前任務時如何再利用它們等相關。 |
解決方案 | 在需要一個 Reusable 物件時,Client 呼叫 ReusablePool 的 acquireReusable() 。如果池是空的,那麼此方法會建立一個 Reusable 物件(如果可以)或者是等待到其他 Reusable 返回池中。 |
參與者與協作者 | ReusablePool 管理著 Client 所用的 Reusable 的可用性。ReusablePool 包含所有 Reusable 物件,如此可以統一管理。 |
效果 | 適用於對物件的需求一直非常穩定的時候,需求變化太大會帶來性能問題。 |
實作 | 如果可建立的物件有限制數量,或者池的大小有限制,可以使用簡單的陣列來實作池。否則,使用 Vector 物件,負責管理 object pool 的物件必須是唯一能夠建立這些物件的物件。ReusablePool 是用 singleton 模式實作的。另一種變體是在 Reusable 新增一個釋放方法 —— 讓它自己回池裡。 |
以上便是 object pool 模式的介紹,下一篇會介紹下一個設計模式:Factory Method 模式。